package cn.tedu.charging.device.dao.repository.Impl;

import cn.tedu.charging.device.dao.repository.StationCacheRepository;


import cn.tedu.charging.device.pojo.po.StationPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;


import java.math.BigDecimal;
import java.util.*;


@Slf4j
@Repository("GEOANDGEO")

public class StationCacheGEOANDGEORepositoryImpl implements StationCacheRepository {

    @Autowired
    RedisTemplate redisTemplate;



    @Override
    public void save(List<StationPO> stationPOS) {
        Map<StationPO, Point> map=new HashMap<StationPO,Point>();  //  1 将站点信息与位置信息放在一起
//为什么说这里的map在redis数据库value的位置上是String类型，因为在redisConfig里面配置使用的是Json格式

        for (StationPO stationPO : stationPOS){
            //获取经度
            BigDecimal stationLng = stationPO.getStationLng();
            //获取维度
            BigDecimal stationLat = stationPO.getStationLat();
            //把BigDecimal转换为String 通过方法toEngineeringString
            String engineerString=stationLng.toEngineeringString();
            //把String转换为Double
            Double lng=Double.valueOf(engineerString);
            String engineerString2=stationLat.toEngineeringString();
            Double lat=Double.valueOf(engineerString2);
            //通过经纬度 构建RedisGEO 中的点 Point
            Point point = new Point(lng, lat);
//            1 方法是将站点的详细信息和位置信息存在一起
            map.put(stationPO,point);
//



        }
        //定义操作geo的 operations 同时绑定key  stations
        BoundGeoOperations stations=redisTemplate.boundGeoOps("stations");

        stations.add(map);



    }

    @Override
    public List<StationPO> search(Double longitude, Double latitude, Double distance) {
        //定义操作geo的 operations 同时绑定key  stations
        BoundGeoOperations stations = redisTemplate.boundGeoOps("stations");

        Circle circle  = getCircle(longitude,latitude,distance);
        log.debug("通过RedisGEO Circle:{} 查询附近充电站",circle);
        GeoResults<RedisGeoCommands.GeoLocation<StationPO>> radius = stations.radius(circle);
        log.debug("通过RedisGEO Circle:{} 查询附近充电站:{}",circle,radius);

        List<StationPO> stationPOS = new ArrayList<>();

        for (GeoResult<RedisGeoCommands.GeoLocation<StationPO>> geoLocationGeoResult : radius) {
            //GeoResults 里的具体内容 用 content表示
            RedisGeoCommands.GeoLocation<StationPO> content =
                    geoLocationGeoResult.getContent();
            //name 表示 GEOADD 命令里的 参数  member
            StationPO name = content.getName();
            stationPOS.add(name);
        }

        return stationPOS;

    }

    /**
     * 通过点和半径构建一个圆
     * @param longitude
     * @param latitude
     * @param distance
     * @return
     */

    private Circle getCircle(Double longitude, Double latitude, Double distance) {
        //通过入参的经纬度 构建一个点
        Point point = new Point(longitude, latitude);
//        通过入参的距离  设置班级 同时设置单位KILOMETERS
        Distance geoDistance = new Distance(distance, Metrics.KILOMETERS);
//        通过点和半径  画圆形
        Circle circle = new Circle(point, geoDistance);

        return circle;
    }
}
